<?php
declare(strict_types=1);

namespace App\Service;

use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\SysRoleDao;
use App\Model\Dao\SysAccessDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use App\Utils\ArrayUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Database\Query\Builder;

class SysRoleService
{
    /**
     * @Inject()
     * @var SysRoleDao
     */
    private $SysRoleDao;

    /**
     * @Inject()
     * @var SysAccessDao
     */
    private $SysAccessDao;

    public function get($param)
    {
        $result = $this->SysRoleDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if(isset($result['createTime'])){
            $result['createTime'] = DateUtils::getDateTime($result['createTime']);
        }
        $nodeIds = $this->SysAccessDao->getNodeListByRoleId($result['id']);
        $result['nodeIds'] = empty($nodeIds) ?  '' : implode(',', array_column($nodeIds, 'nodeId'));
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function del($param)
    {
        $result = $this->SysRoleDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        
        try {
            $result = $this->SysRoleDao->del($param['id'],false);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DEL_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function add($param)
    {
        $data = $param;
        $data['id'] = CustomUtils::createUUID();
        $data['createTime'] = time();        
        CustomUtils::xzxDebug($data);
        unset($data['uid']);

        // Db::beginTransaction();
        try {
            $this->SysRoleDao->insert($data);
        } catch (\Throwable $th) {
            // Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }
        // Db::commit();
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function edit($param)
    {
        $info = $this->SysRoleDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $roleResult = $this->isSuperRole($param['id']);
        if(!$roleResult['code'] && $param['status'] != 1){            
            throw new XZXValidationException('不能禁用超级管理员角色');
        }

        $id = $param['id'];
        $data = array();        

        foreach($param as $k => $v){           
            if(isset($v)){
                $data[$k] = $v;
            }
        }
        CustomUtils::xzxDebug($data);
        unset($data['id']);
        unset($data['uid']);
        
        try {
            $this->SysRoleDao->update($id, $data);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function list(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];        

        $total = $this->SysRoleDao->getCount($param);
        $list = $this->SysRoleDao->getList($param, $page, $limit);

        CustomUtils::xzxDebug($list);

        foreach ($list as $key=>$val){
            $node_data = $this->SysAccessDao->getNodeListByRoleId($val['id']);
//            xeDebug($node_data);
            $tmp = array();
            foreach ($node_data as $v)
            {
                $tmp[]['id'] = $v['nodeId'];
            }
            $list[$key]['nodeIdList'] = $tmp;
        }

        $typeList = $this->SysRoleDao->getTypeList();

        foreach ($list as $k => $v) {
            // CustomUtils::xzxDebug($v);

            $v['strType']    = $this->SysRoleDao->strType($v['type']);;
            $v['strStatus']  = $this->SysRoleDao->strStatus($v['status']);

            if(isset($v['createTime'])){
                $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            }
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }    

    public function isSuperRole($roleId){

        //选超级管理员角色类型
        $result = $this->SysRoleDao->getWhere(["id" => $roleId, "type" => 1]);
        // CustomUtils::xzxDebug($result);
        if(!$result){             
            return CustomUtils::xeServiceReturnData(XZXResponseCode::FAILED_CODE,XZXResponseCode::getMessage(XZXResponseCode::FAILED_CODE),CustomUtils::xzxEmptyObject());
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function getStatusOptions () {
        $arr = $this->SysRoleDao->getStatusList();
        $options = ArrayUtils::ArrToOptions($arr);
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$options);
    }

    public function getOptions ($param) {
        $where = ['status' => 1];
        isset($param['extraType']) && $where['extraType'] = $param['extraType'];
        $list = $this->SysRoleDao->getList($where);
        $options = [];
        foreach ($list as $k => $v) {
            $options[] = ['value' => $v['id'], 'label' => $v['name'], 'extraType' => $v['extraType']];
        }
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$options);
    }

    public function getAccess(array $param) {

        $result = $this->SysAccessDao->getByRoleIdAndShowStatus($param['id'], $param['showStatus']);
        // CustomUtils::xzxDebug($result);
        $data = array_column($result, 'nodeId');        
        // CustomUtils::xzxDebug($data);
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }


    public function setAccess(array $param) {

        $info = $this->SysRoleDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        DB::beginTransaction();

        try {
            // 先删除
            $this->SysAccessDao->delByRoleIdAndShowStatus($param['id'], $param['showStatus']);
            // 再新增
            $nodeIds = explode(',', $param['nodeIds']);
            $data = [];
            foreach ($nodeIds as $value) {
                array_push($data, [
                    'id'         => CustomUtils::createUUID(),
                    'roleId'     => $param['id'],
                    'nodeId'     => $value,
                    'status'     => 1,
                    'createTime' => time()
                ]);
            }
            try {
                $this->SysAccessDao->add($data);
            } catch (\Throwable $th) {
                throw $th;
            }
        } catch (\Throwable $th) {
            Db::rollBack();            
            throw new XZXValidationException('更新权限失败');
        }

        DB::commit();
        
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }
    
}